package com.qkl.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qkl.user.dto.user.LevelDistributionDTO;
import com.qkl.user.entity.MatrixRelation;
import com.qkl.user.mapper.MatrixRelationMapper;
import com.qkl.user.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.web3j.tuples.generated.Tuple3;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequiredArgsConstructor
@Service
public class MatrixServicesImpl {

    @Autowired
    private MatrixRelationMapper matrixRelationMapper;

    /**
     * 统计指定用户节点下，1-16层的分布情况
     * 性能：单次数据库查询，内存中进行聚合计算。O(N)，N为16层内的总节点数。
     */
    public List<LevelDistributionDTO> calculateLevelDistribution(Long rootUserId) {
        // 1. 获取根节点信息
        MatrixRelation rootRelation = matrixRelationMapper.selectByUserId(rootUserId);
        if (rootRelation == null) {
            throw new IllegalArgumentException("用户 " + rootUserId + " 不存在于矩阵中。");
        }

        String rootPath = rootRelation.getPath();
        int rootLevel = rootRelation.getLevel();
        int endLevel = rootLevel + 15; // 计算到16层

        // 2. 一次性查询出16层内所有后代的用户ID
//        List<Long> descendantUserIds = matrixRelationMapper.selectDescendantUserIdsInLevelRange(
//                rootPath, rootLevel + 1, endLevel);
//
//        if (descendantUserIds.isEmpty()) {
//            return initializeEmptyDistribution();
//        }

        // 3. 批量查询这些用户的等级信息
//        List<Map<String, Object>> userLevelInfos = sysUserMapper.selectUserLevelInfoByIds(descendantUserIds);
       // Map<Long, String> userLevelInfos = matrixRelationMapper.selectUserLevelsBatch(descendantUserIds);

        // 4. 构建用户ID -> (层级, 等级排序, 等级名称) 的映射
       // Map<Long, Tuple3<Integer, Integer, String>> userIdInfoMap = new HashMap<>();
//        for (Map<String, Object> info : userLevelInfos) {
//            Long userId = ((Number) info.get("id")).longValue();
//            MatrixRelation relation = matrixRelationMapper.selectByUserId(userId); // 这里可以优化，将level也放入第二步查询
//            if (relation != null) {
//                Integer level = relation.getLevel();
//                Integer levelSort = info.get("level_sort") != null ? ((Number) info.get("level_sort")).intValue() : -1;
//                String levelName = info.get("level_name") != null ? (String) info.get("level_name") : "未知";
//                userIdInfoMap.put(userId, new Tuple3<>(level, levelSort, levelName));
//            }
//        }

        // *优化点：* 第2步的SQL可以修改为JOIN `matrix_relation` 和 `sys_user` 以及 `user_level`，
        // 直接查询出每个后代的 (level, level_sort, level_name)，避免第4步的循环查询。
        // 为了代码清晰，这里展示了标准做法，实际项目中应采用JOIN优化。

        // 5. 初始化结果列表
       List<LevelDistributionDTO> result = initializeEmptyDistribution();
//
//        // 6. 在内存中聚合计算
//        for (Map.Entry<Long, Tuple3<Integer, Integer, String>> entry : userIdInfoMap.entrySet()) {
//            Tuple3<Integer, Integer, String> info = entry.getValue();
//            int relativeLevel = info._1() - rootLevel; // 计算相对于根节点的层级
//
//            if (relativeLevel >= 1 && relativeLevel <= 16) {
//                LevelDistributionDTO dto = result.get(relativeLevel - 1);
//                dto.setUserCount(dto.getUserCount() + 1);
//
//                // 更新最高等级
//                if (info._2() > -1) { // 如果有等级
//                    if (dto.getHighestLevelName().isEmpty() || info._2() > getLevelSort(dto.getHighestLevelName())) {
//                        dto.setHighestLevelName(info._3());
//                    }
//                }
//            }
//        }

        // 为了简化，这里假设等级名称是唯一的。如果不是，`getLevelSort` 需要一个从名称到排序的映射。
        // 更严谨的做法是在聚合时跟踪最高等级的sort值。

        return result;
    }
// --- 辅助方法 ---

    private List<LevelDistributionDTO> initializeEmptyDistribution() {
        List<LevelDistributionDTO> distribution = new ArrayList<>(16);
        for (int i = 1; i <= 16; i++) {
            distribution.add(new LevelDistributionDTO(i));
        }
        return distribution;
    }


}
